package com.itfreer.data.general;

import com.itfreer.data.general.domain.DomainType;
import com.itfreer.utils.StringUtils;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;

/**
 * 定义ITable基类，实现基于元数据和工作空间的数据操作 2015.9.3
 */
public abstract class TableBase implements ITable {

	private Field[] autoFields;

	/**
	 * 获取字段信息
	 */
	protected abstract HashMap<String, Field> fields();

	private Field[] getFields;

	private Field[] keyNoAutoFields;
	private Field[] uniqueFields;

	private HashMap<String, List<Field>> uniqueFieldDic;

	private String onlyCanShowSelectedFields;

	private String allSelectedFields;

	private Field[] keyFields;

	private Field[] keyAndAutoFields;

	private boolean tableIsInit = false;

	/**
	 * 获取表名称
	 */
	@Override
	public String getTableName() {
		return this.getMetadataTableName();
	}

	/**
	 * 获取结构表名称
	 */
	@Override
	public abstract String getMetadataTableName();

	/**
	 * 获取结构表别名
	 */
	@Override
	public abstract String getMetadataTableAliasName();

	/**
	 * 获取表类型
	 */
	@Override
	public TableType getTableType() {
		return TableType.Table;
	}

	/**
	 * 获取字段信息
	 */
	@Override
	public Field[] getFields() {
		if (getFields != null) {
			return getFields;
		}

		if (fields() == null) {
			return null;
		}
		getFields = fields().values().toArray(new Field[fields().size()]);
		return getFields;
	}

	/**
	 * 获取字段总数
	 */
	@Override
	public int getFieldCount() {
		return fields().values().size();
	}

	/**
	 * 获取主键，非自动填充
	 */
	@Override
	public Field[] getKeyNoAutoFields() {
		if (keyNoAutoFields != null) {
			return keyNoAutoFields;
		}

		Collection<Field> fields = fields().values();
		if (fields == null)
			return null;

		List<Field> keys = new ArrayList<Field>();
		for (Field item : fields) {
			if (item.getIsKey() && !item.getIsAuto())
				keys.add(item);
		}
		keyNoAutoFields = keys.toArray(new Field[keys.size()]);
		return keyNoAutoFields;
	}

	/**
	 * 获取唯一值，非key和auto
	 */
	@Override
	public Field[] getUniqueFields() {
		if (uniqueFields != null) {
			return uniqueFields;
		}

		Collection<Field> fields = fields().values();
		if (fields == null)
			return null;

		List<Field> keys = new ArrayList<Field>();
		for (Field item : fields) {
			if (!StringUtils.IsNullOrSpace(item.getUniqueGroup()))
				keys.add(item);
		}
		uniqueFields = keys.toArray(new Field[keys.size()]);
		return uniqueFields;
	}

	/**
	 * 获取唯一值分组缓存
	 * 
	 * @return
	 */
	@Override
	public HashMap<String, List<Field>> getUniqueFieldMap() {
		if (uniqueFieldDic != null) {
			return uniqueFieldDic;
		}
		uniqueFieldDic = new HashMap<String, List<Field>>();
		for (Field item : getUniqueFields()) {
			String key = item.getUniqueGroup().trim().toUpperCase();
			if (uniqueFieldDic.containsKey(key)) {
				uniqueFieldDic.get(key).add(item);
				uniqueFieldDic.put(key, uniqueFieldDic.get(key));
			} else {
				List<Field> items = new ArrayList<Field>();
				items.add(item);
				uniqueFieldDic.put(key, items);
			}
		}
		return uniqueFieldDic;
	}

	/**
	 * 获取自动增值字段
	 */
	@Override
	public Field[] getAutoFields() {
		if (autoFields != null) {
			return autoFields;
		}
		Collection<Field> fields = fields().values();
		if (fields == null)
			return null;

		List<Field> keys = new ArrayList<Field>();
		for (Field item : fields) {
			if (item.getIsAuto())
				keys.add(item);
		}
		autoFields = keys.toArray(new Field[keys.size()]);
		return autoFields;
	}

	/**
	 * 获取查询字符串
	 */
	@Override
	public String getSelectFields(boolean onlyCanShow) {
		if (onlyCanShow) {
			if (onlyCanShowSelectedFields != null) {
				return onlyCanShowSelectedFields;
			}
		} else {
			if (allSelectedFields != null) {
				return allSelectedFields;
			}
		}

		Collection<Field> fields = fields().values();
		if (fields == null)
			return null;

		String selectFields = "";
		for (Field item : fields) {
			if (onlyCanShow) {
				if (item.getCanShow()) {
					selectFields += "[" + item.getFieldName() + "],";
				}
			} else {
				selectFields += "[" + item.getFieldName() + "],";
			}
		}
		if (!StringUtils.IsNullOrSpace(selectFields))
			selectFields = selectFields.substring(0, selectFields.length() - 1);

		if (onlyCanShow) {
			onlyCanShowSelectedFields = selectFields;
		} else {
			allSelectedFields = selectFields;
		}
		return selectFields;
	}

	/**
	 * 根据字段名获取字段信息 fieldName 字段名
	 */
	@Override
	public Field getField(String fieldName) {
		if (fields() == null)
			return null;

		fieldName = fieldName.toUpperCase().trim();
		if (fields().containsKey(fieldName))
			return fields().get(fieldName);
		else
			return null;
	}

	/**
	 * 获取主键
	 */
	@Override
	public Field[] getKeyFields() {
		if (keyFields != null) {
			return keyFields;
		}
		Collection<Field> fields = fields().values();
		if (fields == null)
			return null;

		List<Field> keys = new ArrayList<Field>();
		for (Field item : fields) {
			if (item.getIsKey())
				keys.add(item);
		}
		keyFields = keys.toArray(new Field[keys.size()]);
		return keyFields;
	}

	/**
	 * 获取主键
	 */
	@Override
	public Field[] getKeyAndAutoFields() {
		if (keyAndAutoFields != null) {
			return keyAndAutoFields;
		}
		Collection<Field> fields = fields().values();
		if (fields == null)
			return null;

		List<Field> keys = new ArrayList<Field>();
		for (Field item : fields) {
			if (item.getIsKey() || item.getIsAuto())
				keys.add(item);
		}
		keyAndAutoFields = keys.toArray(new Field[keys.size()]);
		return keyAndAutoFields;
	}

	/**
	 * 获取或设置数据字典表代码字段名
	 */
	@Override
	public String getCodeFieldName() {
		return null;
	}

	/**
	 * 获取或设置数据字典表值字段名
	 */
	@Override
	public String getCaptionFieldName() {
		return null;
	}

	/**
	 * 获取或设置树形表ID字段名
	 */
	@Override
	public String getIDFieldName() {
		return null;
	}

	/**
	 * 获取或设置树形表PID字段名
	 */
	@Override
	public String getPIDFieldName() {
		return null;
	}

	/**
	 * 表关系
	 */
	@Override
	public RelationNode getRelation() {
		return null;
	}

	/**
	 * 获取简单分组
	 */
	@Override
	public abstract String getTableGroup();

	/**
	 * 获取排序字段名
	 */
	@Override
	public String getOrderFieldName() {
		return null;
	}

	/**
	 * 获取是否使用字段名
	 */
	@Override
	public String getIsUsedFieldName() {
		return null;
	}

	/**
	 * 获取是否可编辑字段名
	 */
	@Override
	public String getIsEditFieldName() {
		return null;
	}
	
	/**
	 * 获取是否可编辑字段名
	 */
	@Override
	public String getUnitFieldName() {
		return null;
	}

	/**
	 * 获取级别字段名
	 */
	@Override
	public String getLevelFieldName() {
		return null;
	}
	
	/**
	 * 获取是否为叶子节点字段名
	 */
	@Override
	public String getIsChildFieldName() {
		return null;
	}

	/**
	 * 获取字典阈名称
	 */
	@Override
	public String getDomainFieldName() {
		return null;
	}

	/**
	 * 获取GUID字段名称
	 */
	@Override
	public String getGUIDFieldName() {
		return RowBase.FIELD_GUID;
	}

	/**
	 * 获取版本字段名称
	 */
	@Override
	public String getVersionFieldName() {
		return "";
	}
	
	/**
	 * 是否是代码表
	 */
	@Override
	public DomainType getDomainType(){
		return DomainType.No;
	}

	/**
	 * 获取当前表空间
	 */
	@Override
	public IWorkspace getWorkspace() {
		IWorkspaceFactory workspaceFactory = WorkspaceFactoryClass.install;
//        Application.gainContext()
		IWorkspace pWorkspace = workspaceFactory.openWorkspace(null);
		tableInit(pWorkspace);
		return pWorkspace;
	}

	private void tableInit(IWorkspace pWorkspace) {
		if (tableIsInit) {
			return;
		}
		if (!pWorkspace.objectExist(this.getTableName())) {
			pWorkspace.createTable(this, getTableName());
		}
		tableIsInit = true;
	}

	/**
	 * 获取当前元数据表空间
	 */
	@Override
	public ITableFactory getTableFactory() {
		return TableFactoryClass.install;
	}

	/**
	 * 开始编辑
	 */
	@Override
	public void startEditing() {
		getWorkspace().startEditing();
	}

	/**
	 * 停止编辑
	 */
	@Override
	public void stopEditing(boolean saveEdits) {
		getWorkspace().stopEditing(saveEdits);
	}

	/**
	 * 当前是否处于编辑状态
	 */
	@Override
	public boolean getIsBeingEdited() {
		return getWorkspace().isBeingEdited();
	}

	/**
	 * 执行SQL语句返回查询结果object
	 * 
	 * @param queryMap
	 * @return
	 */
	@Override
	public Object getExecuteScalar(IQueryMap queryMap) {
		return getWorkspace().getExecuteScalar(this,
				queryMap);
	}

	/**
	 * 将数据绑定到自定义数据类型上
	 * 
	 * @param queryMap
	 * @return
	 */
	@Override
	public <T extends RowBase> List<T> getEntityList(Class<T> c, IQueryMap queryMap) {
		return getWorkspace().getEntityList(c, this,
				queryMap);
	}

	/**
	 * 分页查询
	 * 
	 * @param queryMap
	 * @return
	 */
	@Override
	public <T extends RowBase> List<T> pageSelect(Class<T> c, IQueryMap queryMap) {
		return getWorkspace().pageSelect(c, this, queryMap);
	}

	/**
	 * 获取某列的最大值
	 * 
	 * @param fieldName
	 * @return
	 */
	@Override
	public long getSpecFieldMaxValue(String fieldName, HashMap<String, Object> where) {
		return getWorkspace().getSpecFieldMaxValue(this, fieldName, where);
	}

	/**
	 * 获取某列的最小值
	 * 
	 * @param fieldName
	 * @return
	 */
	@Override
	public long getSpecFieldMinValue(String fieldName, HashMap<String, Object> where) {
		return getWorkspace().getSpecFieldMinValue(this, fieldName, where);
	}
	
	@Override
	public <T extends RowBase> T getEntity(Class<T> c, IQueryMap queryMap) {
		return getWorkspace().getEntity(c, this, queryMap);
	}

	@Override
	public <T extends RowBase> T getNextEntity(Class<T> c, RowBase t,
			String byFieldName, HashMap<String, Object> whereMap, OrderByType orderByType,
			boolean addCaptionField) {
		return getWorkspace().getNextEntity(c, this, t, byFieldName, whereMap, orderByType, addCaptionField);
	}

	@Override
	public <T extends RowBase> T getPerEntity(Class<T> c, RowBase t,
			String byFieldName, HashMap<String, Object> whereMap, OrderByType orderByType,
			boolean addCaptionField) {
		return getWorkspace().getNextEntity(c, this, t, byFieldName, whereMap, orderByType, addCaptionField);
	}

	/**
	 * 更新或添加行
	 * 
	 * @param entity
	 * @return
	 */
	@Override
	public void save(RowBase entity) {
		getWorkspace().save(this, entity);
	}

	/**
	 * 更新或添加行
	 * 
	 * @param entity
	 * @return
	 */
	@Override
	public <T extends RowBase> void save(List<T> entity) {
		getWorkspace().save(this, entity);
	}

	/**
	 * 更新或添加行
	 * 
	 * @param entity
	 * @return
	 */
	@Override
	public void insert(RowBase entity) {
		getWorkspace().insert(this, entity);
	}

	/**
	 * 更新或添加行
	 * 
	 * @param entity
	 * @return
	 */
	@Override
	public <T extends RowBase> void insert(List<T> entity) {
		getWorkspace().insert(this, entity);
	}

	/**
	 * 更新或添加行
	 * 
	 * @param entity
	 * @return
	 */
	@Override
	public void update(RowBase entity) {
		getWorkspace().update(this, entity);
	}

	/**
	 * 更新或添加行
	 * 
	 * @param entity
	 * @return
	 */
	@Override
	public <T extends RowBase> void update(List<T> entity) {
		getWorkspace().update(this, entity);
	}

	/**
	 * 更新数据
	 * 
	 * @param updateFilter
	 */
	@Override
	public void update(IUpdateMap updateFilter) {
		getWorkspace().update(this, updateFilter);
	}

	/**
	 * 删除表记录
	 * 
	 * @param queryMap
	 */
	@Override
	public void delete(IQueryMap queryMap) {
		getWorkspace().delete(this, queryMap);
	}

	/**
	 * 删除记录行
	 */
	@Override
	public void delete(String guid) {
		IQueryMap queryMap = new QueryMap();
		queryMap.getWhereMap().put(this.getGUIDFieldName(), guid);
		getWorkspace().delete(this, queryMap);
	}
	
	/**
	 * 删除记录行
	 */
	@Override
	public void delete(List<String> guids) {
		IQueryMap queryMap = new QueryMap();
		String ids =  "";
		for(String guid : guids){
			ids += "'" + guid + "',";
		}
		ids = ids.substring(0, ids.length()-1);
		queryMap.getWhereMap().put(this.getGUIDFieldName()+":in", ids);
		getWorkspace().delete(this, queryMap);
	}

	/**
	 * 添加字段
	 */
	public void addField(Field field) {
		if (field != null && !StringUtils.IsNullOrSpace(field.getFieldName())) {
			if (fields().containsKey(field.getFieldName().toUpperCase().trim())) {
				fields().put(field.getFieldName().toUpperCase().trim(), field);
				this.getWorkspace().updateTable(this, this.getTableName());
			}
		}
	}

	/**
	 * 移除字段
	 */
	public void removeField(Field field) {
		if (field != null && !StringUtils.IsNullOrSpace(field.getFieldName())) {
			if (fields().containsKey(field.getFieldName().toUpperCase().trim())) {
				fields().remove(field.getFieldName().toUpperCase().trim());
				this.getWorkspace().updateTable(this, this.getTableName());
			}
		}
	}

	/**
	 * 更新字段
	 */
	public void updateField(Field field) {
		if (field != null && !StringUtils.IsNullOrSpace(field.getFieldName())) {
			if (fields().containsKey(field.getFieldName().toUpperCase().trim())) {
				fields().put(field.getFieldName().toUpperCase().trim(), field);
				this.getWorkspace().updateTable(this, this.getTableName());
			}
		}
	}
}